package com.compression.tool.ui;

import com.compression.tool.compression.CompressionStrategy;
import com.compression.tool.factory.CompressionStrategyFactory;
import com.compression.tool.model.enums.TaskStatus;
import com.compression.tool.model.enums.TaskType;
import com.compression.tool.model.manager.TaskManager;
import com.compression.tool.model.task.CompressionTask;
import com.compression.tool.model.task.ProgressListener;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author 自然醒
 * @version 1.0
 */

// 压缩选项面板
public class CompressionOptionPanel extends JPanel {
    private JTextField filePathField;//文件路径输入框
    private JButton browseButton; //浏览按钮
    private JComboBox<String> formatCombo; //压缩格式下拉框
    private JSlider levelSlider; //压缩级别滑块
    private JButton compressButton; //压缩按钮
    private JButton decompressButton; //解压按钮
    private JButton cancelButton;//取消按钮
    private JProgressBar progressBar;//进度条

    //使用TaskManager管理任务
    private final TaskManager taskManager;
    private String currentTaskId;
    private List<File> selectedFiles = new ArrayList<>(); // 存储选中的文件和文件夹


    public CompressionOptionPanel() {
        this.taskManager = TaskManager.getInstance();
        setLayout(new BorderLayout());
        initComponents();
        layoutComponents();
    }

    /**
     * 初始化组件
     */
    private void initComponents() {
        filePathField = new JTextField();
        browseButton = new JButton("浏览");
        browseButton.addActionListener(
                e -> {
                    browseForFile();
                }
        );
        formatCombo = new JComboBox<>(new String[]{"ZIP", "RAR", "7Z", "GZ"}); //压缩格式下拉框

        levelSlider = new JSlider(JSlider.HORIZONTAL, 0, 9, 5); //压缩级别滑块
        levelSlider.setMajorTickSpacing(1); //主刻度间隔
        levelSlider.setPaintTicks(true); //绘制刻度
        levelSlider.setPaintLabels(true); //绘制标签

        compressButton = new JButton("压缩");
        compressButton.addActionListener(e -> compressFile());

        decompressButton = new JButton("解压");
        decompressButton.addActionListener(e -> decompressFile());

        cancelButton = new JButton("取消");
        cancelButton.addActionListener(e -> cancel());
        cancelButton.setEnabled(false); //默认禁用取消按钮

        progressBar = new JProgressBar();
        progressBar.setStringPainted(true);
        progressBar.setVisible(false);
    }

    /**
     * 布局组件
     */
    private void layoutComponents() {
        //文件选择面板
        JPanel filePanel = new JPanel(new BorderLayout(5, 5));
        filePanel.setBorder(BorderFactory.createTitledBorder("选择文件"));
        filePanel.add(filePathField, BorderLayout.CENTER);
        filePanel.add(browseButton, BorderLayout.EAST);

        //选项面板
        JPanel optionPanel = new JPanel(new GridLayout(2, 2, 5, 5));
        optionPanel.setBorder(BorderFactory.createTitledBorder("压缩选项"));
        optionPanel.add(new JLabel("压缩格式:"));
        optionPanel.add(formatCombo);
        optionPanel.add(new JLabel("压缩级别:"));
        optionPanel.add(levelSlider);

        //按钮面板
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
        buttonPanel.add(compressButton);
        buttonPanel.add(decompressButton);
        buttonPanel.add(cancelButton);

        //创建一个包含按钮面板和进度条的面板
        JPanel southPanel = new JPanel(new BorderLayout());
        southPanel.add(buttonPanel, BorderLayout.NORTH);
        southPanel.add(progressBar, BorderLayout.SOUTH);

        //主布局
        add(filePanel, BorderLayout.NORTH);
        add(optionPanel, BorderLayout.CENTER);
        add(southPanel, BorderLayout.SOUTH);
    }

    private void browseForFile() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("选择文件或文件夹");
        fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        fileChooser.setMultiSelectionEnabled(true);
        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            File[] selectedArray = fileChooser.getSelectedFiles();
            selectedFiles.clear();
            StringBuilder fileNames = new StringBuilder();
            for (File file : selectedArray) {
                selectedFiles.add(file);
                if(fileNames.length() > 0){
                    fileNames.append("; ");
                }
                fileNames.append(file.getName());
            }
            filePathField.setText(fileNames.toString());
            //如果选择了多个项目，在文本框后面显示数量
            if (selectedArray.length > 1) {
                filePathField.setToolTipText("已选择: "+selectedArray.length + " 个文件");
            }else{
                filePathField.setToolTipText(selectedArray[0].getAbsolutePath());
            }
        }
    }

    /**
     * 压缩文件
     */
    private void compressFile() {

        //已有任务运行，先进行取消
        if (currentTaskId != null) {
            CompressionTask currentTask = taskManager.getTask(currentTaskId);
            if (currentTask != null && (currentTask.getStatus() == TaskStatus.RUNNING
                    || currentTask.getStatus() == TaskStatus.PAUSED)) {
                int result = JOptionPane.showConfirmDialog(this,
                        "已有任务正在运行，是否取消当前任务并开始新的任务？", "提示",
                        JOptionPane.YES_NO_OPTION);
                if (result != JOptionPane.YES_OPTION) {
                    return;
                }
                cancelCurrentTask();
            }
        }

        if(selectedFiles.isEmpty()){
            JOptionPane.
                    showMessageDialog(this, "请选择要压缩的文件", "提示",
                            JOptionPane.WARNING_MESSAGE);
            return;
        }

        // 验证所有文件都存在
        for (File file : selectedFiles) {
            if (!file.exists()) {
                JOptionPane.showMessageDialog(this, "文件不存在: " + file.getName(), "提示",
                        JOptionPane.WARNING_MESSAGE);
                return;
            }
        }

        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("选择保存位置");
        String format = (String) formatCombo.getSelectedItem();
        String compressedFileName = "";
        if(selectedFiles.size() == 1){
            File sourceFile = selectedFiles.get(0);
            String[] nameParts = sourceFile.getName().split("\\.");
            compressedFileName = nameParts[0];
        }else{
            compressedFileName = "多个文件";
        }
        fileChooser.setSelectedFile(new File(compressedFileName + "." + format.toLowerCase()));

        int res = fileChooser.showSaveDialog(this);
        if (res != JFileChooser.APPROVE_OPTION) {
            return;
        }

        File outputFile = fileChooser.getSelectedFile();
        int compressionLevel = levelSlider.getValue();

        //使用策略工厂
        CompressionStrategy strategy = CompressionStrategyFactory.getStrategy(format);
        if (strategy == null) {
            JOptionPane.showMessageDialog(this, "不支持的压缩格式",
                    "提示", JOptionPane.WARNING_MESSAGE);
            return;
        }

        CompressionTask task = new CompressionTask(
                UUID.randomUUID().toString(),
                TaskType.COMPRESS,
                selectedFiles,
                outputFile,
                strategy,
                compressionLevel
        );

        //设置监听器
        task.setProgressListener(new ProgressListener() {
            @Override
            public void onProgressUpdate(double progress) {
                SwingUtilities.invokeLater(() -> {
                    progressBar.setValue((int) progress);
                    progressBar.setString(String.format("%.1f%%", progress));
                });
            }

            @Override
            public void onStatusChange(TaskStatus status) {
                SwingUtilities.invokeLater(() -> {
                    progressBar.setIndeterminate(status == TaskStatus.RUNNING);
                    progressBar.setString(status.toString());
                    updateCancelButtonState();
                });
            }

            @Override
            public void onTaskComplete(boolean success, String message) {
                SwingUtilities.invokeLater(() -> {
                    progressBar.setVisible(false);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(0);
                    currentTaskId = null;
                    updateCancelButtonState();
                    if (success) {
                        JOptionPane.showMessageDialog(CompressionOptionPanel.this,
                                message, "完成", JOptionPane.INFORMATION_MESSAGE);
                    } else {
                        JOptionPane.showMessageDialog(CompressionOptionPanel.this,
                                message, "错误", JOptionPane.ERROR_MESSAGE);
                    }
                });
            }
        });

        //通过TaskManager提交任务
        currentTaskId = taskManager.submitTask(task);

        SwingUtilities.invokeLater(() -> {
            progressBar.setVisible(true);
            progressBar.setValue(0);
            progressBar.setIndeterminate(true);
            updateCancelButtonState();
        });

    }

    /**
     * 解压文件
     */
    private void decompressFile() {
        //已有任务运行，先进行取消
        if (currentTaskId != null) {
            CompressionTask currentTask = taskManager.getTask(currentTaskId);
            if (currentTask != null && (currentTask.getStatus() == TaskStatus.RUNNING
                    || currentTask.getStatus() == TaskStatus.PAUSED)) {
                int result = JOptionPane.showConfirmDialog(this,
                        "已有任务正在运行，是否取消当前任务并开始新的任务？", "提示",
                        JOptionPane.YES_NO_OPTION);
                if (result != JOptionPane.YES_OPTION) {
                    return;
                }
                cancelCurrentTask();
            }
        }
        if (selectedFiles.size() != 1) {
            JOptionPane.showMessageDialog(this, "请选择一个压缩文件进行解压", "提示", JOptionPane.WARNING_MESSAGE);
            return;
        }

        File sourceFile = selectedFiles.get(0);
        if (!sourceFile.exists()) {
            JOptionPane.showMessageDialog(this, "文件不存在", "提示", JOptionPane.WARNING_MESSAGE);
            return;
        }

        //根据文件拓展名自动选择解压策略
        String fileName = sourceFile.getName();
        String format = "";
        int lastIndex = fileName.lastIndexOf(".");
        if (lastIndex > 0) {
            format = fileName.substring(lastIndex + 1);
        }
        CompressionStrategy strategy = CompressionStrategyFactory.getStrategy(format);
        if (strategy == null) {
            JOptionPane.showMessageDialog(this,
                    "不支持的文件格式: " + format + "，请手动选择格式",
                    "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("选择解压目标目录");
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

        int result = fileChooser.showOpenDialog(this);
        if (result != JFileChooser.APPROVE_OPTION) {
            return;
        }

        File outputDir = fileChooser.getSelectedFile();

        CompressionTask task = new CompressionTask(
                UUID.randomUUID().toString(),
                TaskType.DECOMPRESS,
                List.of(sourceFile),
                outputDir,
                strategy,
                0
        );

        // 设置监听器
        task.setProgressListener(new ProgressListener() {
            @Override
            public void onProgressUpdate(double progress) {
                SwingUtilities.invokeLater(() -> {
                    progressBar.setValue((int) progress);
                    progressBar.setString(String.format("%.1f%%", progress));
                });
            }

            @Override
            public void onStatusChange(TaskStatus status) {
                SwingUtilities.invokeLater(() -> {
                    progressBar.setIndeterminate(status == TaskStatus.RUNNING);
                    progressBar.setString(status.toString());
                    updateCancelButtonState();
                });
            }

            @Override
            public void onTaskComplete(boolean success, String message) {
                SwingUtilities.invokeLater(() -> {
                    progressBar.setIndeterminate(false);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                    currentTaskId = null;
                    updateCancelButtonState();
                    if (success) {
                        JOptionPane.showMessageDialog(CompressionOptionPanel.this,
                                message, "完成", JOptionPane.INFORMATION_MESSAGE);
                    } else {
                        JOptionPane.showMessageDialog(CompressionOptionPanel.this,
                                message, "错误", JOptionPane.ERROR_MESSAGE);
                    }
                });
            }
        });

        currentTaskId = taskManager.submitTask(task);
        SwingUtilities.invokeLater(() -> {
            progressBar.setVisible(true);
            progressBar.setValue(0);
            progressBar.setIndeterminate(true);
            updateCancelButtonState();
        });

    }

    private void cancel() {
        if (currentTaskId != null) {
            CompressionTask currentTask = taskManager.getTask(currentTaskId);
            if (currentTask != null &&
                    (currentTask.getStatus() == TaskStatus.RUNNING ||
                            currentTask.getStatus() == TaskStatus.PAUSED)) {
                int res = JOptionPane.showConfirmDialog(this,
                        "是否取消当前任务?", "取消任务", JOptionPane.YES_NO_OPTION);
                if (res == JOptionPane.YES_OPTION) {
                    cancelCurrentTask();
                }
            } else {
                JOptionPane.showMessageDialog(this,
                        "没有正在执行的任务", "提示", JOptionPane.INFORMATION_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this,
                    "没有正在执行任务", "提示", JOptionPane.INFORMATION_MESSAGE);
        }
    }

    /**
     * 取消当前任务
     */
    private void cancelCurrentTask() {
        if (currentTaskId != null) {
            boolean cancelled = taskManager.cancelTask(currentTaskId);
            if (cancelled) {
                SwingUtilities.invokeLater(() -> {
                    progressBar.setVisible(false);
                    currentTaskId = null;
                    updateCancelButtonState();
                    JOptionPane.showMessageDialog(CompressionOptionPanel.this,
                            "任务已取消", "提示", JOptionPane.INFORMATION_MESSAGE);
                });
            }
        }
    }

    /**
     * 更新取消按钮状态
     */
    private void updateCancelButtonState() {
        SwingUtilities.invokeLater(() -> {
            boolean hasActiveTask = false;
            if (currentTaskId != null) {
                CompressionTask task = taskManager.getTask(currentTaskId);
                if (task != null && (task.getStatus() == TaskStatus.RUNNING
                        || task.getStatus() == TaskStatus.PAUSED)) {
                    hasActiveTask = true;
                }
            }
            cancelButton.setEnabled(hasActiveTask);
        });
    }


}
